﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvvmCodeReduction.Model;
using MvvmCodeReduction.ViewModel;

namespace MvvmCodeReduction.Tests
{
    [TestClass]
    public class CustomerViewModelTests
    {
        [TestMethod]
        public void Save_Always_ModelNameSetToEditedName()
        {
            // Arrange
            const string expectedName = "expected";
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.EditedName = expectedName;

            // Act
            viewModel.CallSave();

            //Assert
            Assert.AreEqual(expectedName, viewModel.Model.Name);
        }

        [TestMethod]
        public void Save_Always_CallsToggleEditing()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);

            // Act
            viewModel.CallSave();

            //Assert
            Assert.IsTrue(viewModel.ToggleEditingCalled);
        }

        [TestMethod]
        public void Edit_Always_CallsToggleEditing()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);

            // Act
            viewModel.CallEdit();

            //Assert
            Assert.IsTrue(viewModel.ToggleEditingCalled);
        }

        [TestMethod]
        public void ToggleEditing_IsEditing_EditTextCommandSetToEditText()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = true;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.AreEqual(CustomerViewModel.EditText, 
                viewModel.EditCommandText);
        }

        [TestMethod]
        public void ToggleEditing_IsEditing_IsEditingSetToFalse()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = true;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.IsFalse(viewModel.IsEditing);
        }

        [TestMethod]
        public void ToggleEditing_IsEditing_EditedNameSetToStringEmpty()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = true;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.AreEqual(string.Empty, viewModel.EditedName);
        }

        [TestMethod]
        public void ToggleEditing_IsNotEditing_EditCommandTextSetToCancelText()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = false;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.AreEqual(CustomerViewModel.CancelText,
                viewModel.EditCommandText);
        }

        [TestMethod]
        public void ToggleEditing_IsNotEditing_EditedNameSetToModelName()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = false;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.AreEqual(model.Name, viewModel.EditedName);
        }

        [TestMethod]
        public void ToggleEditing_IsNotEditing_IsEditingSetToTrue()
        {
            // Arrange
            Model.Customer model = new Customer(1, "initial");
            CustomerViewModelHarness viewModel
                = new CustomerViewModelHarness(model);
            viewModel.IsEditing = false;

            // Act
            viewModel.CallToggleEditing();

            //Assert
            Assert.IsTrue(viewModel.IsEditing);
        }

        private class CustomerViewModelHarness : CustomerViewModel
        {
            public bool ToggleEditingCalled { get; set; }

            public CustomerViewModelHarness(Customer model) 
                : base(model)
            {
            }

            public void CallSave()
            {
                Save();
            }

            public void CallEdit()
            {
                Edit();
            }

            public void CallToggleEditing()
            {
                base.ToggleEditing();
            }

            protected override void ToggleEditing()
            {
                ToggleEditingCalled = true;
                base.ToggleEditing();
            }
        }
    }
}
